package com.sinosoft.generator.builder;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: BusinessBuilder
 * @ClassNameExplain: 
 * @Description: 
 * @author xzh
 * @date 2016年9月4日 上午1:08:32
 */
public class BusinessBuilder {
	
	private static final String DEFAULT_ENCODING = "UTF-8";
	
	//FreeMarker配置
	Configuration configuration = null;

	public static enum TemplateType {

		API("api"), WEB_VIEW("webview");

		private String type;

		private TemplateType(String type) {
			this.type = type;
		}

		public String getType() {
			return type;
		}
	}

	//模板类型
	private TemplateType tplType;

	//包名
	private String packageName;
	
	//模块名
	private String moduleName;

	//实例名前缀
	private String beanNamePrefix;

	//描述
	private String desc;
	
	//作者
	private String author;
	
	//日期
	private String date;

	//版本
	private String version;

	//接口类request mapping
	private String ctrlMapping;

	//接口方法request mapping
	private String methodMapping;

	//是否清空
	private boolean isCleanDir;

	public TemplateType getTplType() {
		return tplType;
	}

	public BusinessBuilder setTplType(TemplateType tplType) {
		this.tplType = tplType;
		return this;
	}

	public String getPackageName() {
		return packageName;
	}

	public BusinessBuilder setPackageName(String packageName) {
		this.packageName = packageName;
		return this;
	}

	public String getModuleName() {
		return moduleName;
	}

	public BusinessBuilder setModuleName(String moduleName) {
		this.moduleName = moduleName;
		return this;
	}

	public String getBeanNamePrefix() {
		return beanNamePrefix;
	}

	public BusinessBuilder setBeanNamePrefix(String beanNamePrefix) {
		this.beanNamePrefix = beanNamePrefix;
		return this;
	}

	public String getAuthor() {
		return author;
	}

	public BusinessBuilder setAuthor(String author) {
		this.author = author;
		return this;
	}

	public String getDate() {
		return date;
	}

	public BusinessBuilder setDate(String date) {
		this.date = date;
		return this;
	}

	public String getDesc() {
		return desc;
	}

	public BusinessBuilder setDesc(String desc) {
		this.desc = desc;
		return this;
	}

	public String getVersion() {
		return version;
	}

	public BusinessBuilder setVersion(String version) {
		this.version = version;
		return this;
	}

	public String getCtrlMapping() {
		return ctrlMapping;
	}

	public BusinessBuilder setCtrlMapping(String ctrlMapping) {
		this.ctrlMapping = ctrlMapping;
		return this;
	}

	public String getMethodMapping() {
		return methodMapping;
	}

	public BusinessBuilder setMethodMapping(String methodMapping) {
		this.methodMapping = methodMapping;
		return this;
	}

	public boolean isCleanDir() {
		return isCleanDir;
	}

	public BusinessBuilder setCleanDir(boolean cleanDir) {
		isCleanDir = cleanDir;
		return this;
	}

	/**
	 * @Title: build
	 * @TitleExplain: 
	 * @Description:  
	 * @version 1.0.0
	 * @author xzh
	 */
	public void build() {
		String type = this.tplType.getType();
		/**
		 * 初始化configuration
		 */
		configuration = new Configuration(new Version(2, 3, 23));
		configuration.setClassForTemplateLoading(BusinessBuilder.class, "/template/" + type);
		configuration.setDefaultEncoding(DEFAULT_ENCODING);
		//module名全小写
		String moduleNameLowerCase = moduleName.toLowerCase();
		//module名首字母小写
		String moduleNameFirstLowerCase = moduleName.replaceAll("^\\w{1}(.*)$", moduleName.substring(0, 1).toLowerCase() + "$1");
		try {
			/**
			 * 填充数据model
			 */
			Map<String, Object> dataModel = new HashMap<String, Object>();
			dataModel.put("packageName", packageName);
			dataModel.put("moduleName", moduleName);
			dataModel.put("beanNamePrefix", beanNamePrefix);
			dataModel.put("moduleNameLowerCase", moduleNameLowerCase);
			dataModel.put("moduleNameFirstLowerCase", moduleNameFirstLowerCase);
			dataModel.put("author", author);
			dataModel.put("desc", desc);
			dataModel.put("version", version);
			dataModel.put("ctrlMapping", ctrlMapping);
			dataModel.put("methodMapping", methodMapping);
			if(date == null) {
				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
				date = dateFormat.format(new Date());				
			}
			dataModel.put("date", date);
			
			/**
			 * 生成business代码
			 */
			String path = "common-generator/business";
			File dirPathParent = new File(path);
			File dirPathController = new File(path + String.format("/%s/controller", moduleNameLowerCase));
			File dirPathService = new File(String.format(path + "/%s/service", moduleNameLowerCase));
			File dirPathServiceImpl = new File(path + String.format("/%s/service/impl", moduleNameLowerCase));
			File dirPathIO = new File(path + String.format("/%s/io", moduleNameLowerCase));
			File dirPathVO = new File(path + String.format("/%s/vo", moduleNameLowerCase));
			// 需要清空时清空目录
			if(isCleanDir && dirPathParent.exists()) {
				Files.walkFileTree(dirPathParent.toPath(), new SimpleFileVisitor<Path>() {
					@Override
					public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
						Files.delete(file);
						return FileVisitResult.CONTINUE;
					}

					@Override
					public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
						Files.delete(dir);
						return FileVisitResult.CONTINUE;
					}
				});
			}
			if(!dirPathController.exists()) {
				dirPathController.mkdirs();
			}
			if(!dirPathService.exists()) {
				dirPathService.mkdirs();
			}
			if(!dirPathServiceImpl.exists()) {
				dirPathServiceImpl.mkdirs();
			}
			if(!dirPathIO.exists()) {
				dirPathIO.mkdirs();
			}
			if(!dirPathVO.exists()) {
				dirPathVO.mkdirs();
			}
			//Controller
			Template templateController = configuration.getTemplate("TemplateController.ftl");
			templateController.process(dataModel, new OutputStreamWriter(new FileOutputStream(new File(dirPathController, moduleName + "Controller.java")), DEFAULT_ENCODING));
			//Service
			Template templateService = configuration.getTemplate("TemplateService.ftl");
			templateService.process(dataModel, new OutputStreamWriter(new FileOutputStream(new File(dirPathService, "I" + moduleName + "Service.java")), DEFAULT_ENCODING));
			//ServiceImpl
			Template templateServiceImpl = configuration.getTemplate("TemplateServiceImpl.ftl");
			templateServiceImpl.process(dataModel, new OutputStreamWriter(new FileOutputStream(new File(dirPathServiceImpl, moduleName + "ServiceImpl.java")), DEFAULT_ENCODING));
			//IO
			Template templateIO = configuration.getTemplate("TemplateIO.ftl");
			templateIO.process(dataModel, new OutputStreamWriter(new FileOutputStream(new File(dirPathIO, moduleName + "IO.java")), DEFAULT_ENCODING));
			//VO
			Template templateVO = configuration.getTemplate("TemplateVO.ftl");
			templateVO.process(dataModel, new OutputStreamWriter(new FileOutputStream(new File(dirPathVO, moduleName + "VO.java")), DEFAULT_ENCODING));
		
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
}